package ru.ifmo.mlarinsky.classificator.map;

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import ru.ifmo.mlarinsky.classificator.math.MathUtil;
import ru.ifmo.mlarinsky.classificator.providers.InstructionsProvider;

public class MapDifferancePainter extends MapPainter {
    private double maxDist = Double.NEGATIVE_INFINITY;
    private double minDist = Double.POSITIVE_INFINITY;

    @Override
    void paintNode(MapNode mapNode) {
        double value = (Double) mapNode.getValue();
        Color color = (value >= (maxDist + minDist) / 2) ? Color.BLACK : Color.WHITE;

        mapNode.setColor(color);
    }

    @Override
    void preprocessMap(SomMap map) {
        for (MapNode node : map) {
            List<MapNode> neighbours = getNeighbours(map, node);

            double localMaxDist = 0D;
            for (MapNode neighbour : neighbours) {
                localMaxDist = Math.max(localMaxDist, MathUtil.vectDist(node, neighbour));
            }

            minDist = Math.min(localMaxDist, minDist);
            maxDist = Math.max(localMaxDist, maxDist);

            node.setValue(localMaxDist);
        }
    }

    private static List<MapNode> getNeighbours(SomMap map, MapNode node) {
        List<MapNode> neighbours = new ArrayList<MapNode>(4);

        int nodeX = node.getX();
        int nodeY = node.getY();
        int yDim = map.getYDimension();

        int nodeIndex = nodeY * yDim + nodeX;
        int[] neighbourIndexes = {
            nodeIndex - yDim,
            nodeIndex + yDim,
            nodeIndex - 1,
            nodeIndex + 1};

        for (int index : neighbourIndexes) {
            try {
                neighbours.add(map.get(index));
            } catch (IndexOutOfBoundsException e) {
                // Ignore
            }
        }

        return neighbours;
    }

    public static void main(String[] args) {
//        testGetNeighbours();
        testPaintMap();
    }

    private static void testPaintMap() {
        SomMap somMap = MapBuilder.buildMap(InstructionsProvider.DEFAULTS);

        System.out.println("Wrong size = " + (somMap.size() != somMap.getXDimension()  * somMap.getYDimension()));
        new MapDifferancePainter().paintMap(somMap);
    }

    private static void testGetNeighbours() {
        SomMap somMap = MapBuilder.buildMap(InstructionsProvider.DEFAULTS);
 
        for (MapNode mapNode : somMap) {
            List<MapNode> neighbours = getNeighbours(somMap, mapNode);

            StringBuilder sb = new StringBuilder("[" + mapNode.getX() + ", " + mapNode.getY() + "] - > ");
            for (MapNode neighbour : neighbours) {
                sb.append("[").append(neighbour.getX()).append(", ").append(neighbour.getY()).append("] ");
            }

            System.out.println(sb);
        }
    }
}
